/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package botmaker;

import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Vector;
import javax.swing.plaf.metal.OceanTheme;
import org.snmp4j.CommandResponder;
import org.snmp4j.CommandResponderEvent;
import org.snmp4j.CommunityTarget;
import org.snmp4j.PDU;
import org.snmp4j.Snmp;
import org.snmp4j.TransportMapping;
import org.snmp4j.event.ResponseEvent;
import org.snmp4j.mp.SnmpConstants;
import org.snmp4j.smi.*;
import org.snmp4j.transport.DefaultUdpTransportMapping;

public class SNMP4JHelper implements CommandResponder {

    public static final int mSNMPVersion = 0; // 0 represents SNMP version=1
    public static final String OID_MESSAGE = "1.3.6.1.3.55.0.0";
    public static final String OID_USERNAME = "1.3.6.1.3.55.0.1";
    public static final int SNMP_PORT = 161;
    Snmp snmp;
    CommunityTarget comtarget;
    TransportMapping transport;
    String userName;
    HashMap<String, String> nameRegistry = new HashMap<String, String>();
    ArrayList<Message> messages = new ArrayList<Message>();
    MainFrame mainFrame;

    public class Message {

        String ip;
        String message;

        public Message(String ip, String message) {
            int index = ip.lastIndexOf("/");
            if (index >= 0) {
                ip = ip.substring(0, index);
            }
            this.ip = ip;
            this.message = message;
        }

        public String getIp() {
            return ip;
        }

        public String getMessage() {
            return message;
        }
    };

    public SNMP4JHelper(MainFrame mainFrame, String strAddress) {
        this.mainFrame = mainFrame;
        try {
            OctetString communityOctetString = new OctetString("public");
            strAddress = strAddress + "/" + SNMP_PORT;
            Address targetaddress = new UdpAddress(strAddress);
            transport = new DefaultUdpTransportMapping(new UdpAddress("0.0.0.0/161"));

            comtarget = new CommunityTarget();
            comtarget.setCommunity(communityOctetString);
            comtarget.setVersion(SnmpConstants.version1);
            comtarget.setAddress(targetaddress);
            comtarget.setRetries(2);
            comtarget.setTimeout(5000);

            snmp = new Snmp(transport);
            snmp.addCommandResponder(this);
            snmp.listen();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void setUserName(String userName) {
        this.userName = userName;
        try {
            String ip = InetAddress.getLocalHost().getHostAddress();
            nameRegistry.put(ip, userName);
        } catch (UnknownHostException unknownHostException) {
        }
    }

    void close() {
        try {
            if (snmp != null) {
                snmp.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void snmpSet(String strOID, String Value) {
        try {
            PDU pdu = new PDU();
            pdu.add(new VariableBinding(new OID(strOID), new OctetString(Value)));
            pdu.setType(PDU.SET);

            ResponseEvent event = snmp.send(pdu, comtarget);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
    /*
     * The code is valid only SNMP version1. SnmpGet method
     * return Response for given OID from the Device.
     */

    public String snmpGet(String strOID) {
        String str = null;
        try {
            PDU pdu = new PDU();
            pdu.add(new VariableBinding(new OID(strOID)));
            pdu.setType(PDU.GET);

            ResponseEvent response = snmp.get(pdu, comtarget);
            boolean ok = false;
            if (response != null) {
                PDU pduresponse = response.getResponse();
                if (pduresponse != null) {
                    if (pduresponse.getErrorStatusText().equalsIgnoreCase("Success")) {
                        str = pduresponse.getVariableBindings().firstElement().toString();
                        if (str.contains("=")) {
                            int len = str.indexOf("=");
                            str = str.substring(len + 1, str.length());
                        }
                        ok = true;
                    }
                }

            }
            if (!ok) {
                System.out.println("Feeling like a TimeOut occured ");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println(String.format("Response = %s", str));
        return str;
    }

    public void processPdu(CommandResponderEvent event) {
        PDU command = event.getPDU();
        if (command != null) {
            System.out.println("processPdu");
            System.out.println(command.getType());
            if (command.getType() == PDU.GET) {
                Vector v = command.getVariableBindings();
                for (int i = 0; i < v.size(); i++) {
                    VariableBinding vb = (VariableBinding) v.elementAt(i);
                    if (vb.getOid().toString().equals(OID_USERNAME)) {
                        try {
                            PDU pdu = new PDU();
                            pdu.add(new VariableBinding(new OID(OID_USERNAME), new OctetString(userName)));
                            pdu.setType(PDU.RESPONSE);
                            event.setProcessed(true);
                            ResponseEvent re = snmp.send(pdu, comtarget);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }
            } else if (command.getType() == PDU.SET) {
                Vector v = command.getVariableBindings();
                for (int i = 0; i < v.size(); i++) {
                    VariableBinding vb = (VariableBinding) v.elementAt(i);
                    if (vb.getOid().toString().equals(OID_MESSAGE)) {
                        try {
                            String ip = event.getPeerAddress().toString();
                            Variable var = vb.getVariable();
                            String message = var.toString();
                            if (var instanceof OctetString) {
                                byte[] bytes = ((OctetString)(var)).getValue();
                                message = new String(bytes, "ISO-8859-1");
                            }
                            messages.add(new Message(ip, message));
                            mainFrame.updateMessageBoard();
                            event.setProcessed(true);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }
    }

    public ArrayList<Message> getMessages() {
        return messages;
    }

    public String resolveIp(String ip) {
        if (ip != null) {
            String name = nameRegistry.get(ip);
            if (name != null) {
                return name;
            } else {
                final String askIp = ip;
                new Thread(new Runnable() {

                    public void run() {
                        askName(askIp);
                    }
                }).start();
            }
        }
        return "UNKNOWN";
    }

    public void askName(String ip) {
        try {
            String str = null;
            OctetString communityOctetString = new OctetString("public");
            String strAddress = ip + "/" + SNMP_PORT;
            Address targetaddress = new UdpAddress(strAddress);
            TransportMapping transport = new DefaultUdpTransportMapping();
            transport.listen();

            CommunityTarget comtarget = new CommunityTarget();
            comtarget.setCommunity(communityOctetString);
            comtarget.setVersion(SnmpConstants.version1);
            comtarget.setAddress(targetaddress);
            comtarget.setRetries(2);
            comtarget.setTimeout(5000);

            PDU pdu = new PDU();
            ResponseEvent response;
            Snmp snmp;
            pdu.add(new VariableBinding(new OID(OID_USERNAME)));
            pdu.setType(PDU.GET);
            snmp = new Snmp(transport);

            response = snmp.get(pdu, comtarget);
            boolean ok = false;
            if (response != null) {
                PDU pduresponse = response.getResponse();
                if (pduresponse != null) {
                    if (pduresponse.getErrorStatusText().equalsIgnoreCase("Success")) {
                        VariableBinding vb = (VariableBinding)pduresponse.getVariableBindings().firstElement();
                        Variable var = vb.getVariable();
                        str = var.toString();
                        if (var instanceof OctetString) {
                            byte[] bytes = ((OctetString)(var)).getValue();
                            str = new String(bytes, "ISO-8859-1");
                        }
                        if (str.contains("=")) {
                            int len = str.indexOf("=");
                            str = str.substring(len + 1, str.length());
                        }
                        ok = true;
                    }
                }

            }
            snmp.close();
            if (ok) {
                nameRegistry.put(ip, str);
                mainFrame.updateMessageBoard();
            }
        } catch (IOException iOException) {
        }
    }
}
